"""
1-gram分类器核心概念演示
简化版本，专注于理解pooling和深度学习基本概念
"""

import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import rcParams

# 设置中文字体
rcParams['font.sans-serif'] = ['SimHei']
rcParams['axes.unicode_minus'] = False

def demonstrate_pooling_concepts():
    """演示不同pooling策略的核心概念"""
    print("=" * 50)
    print("Pooling策略核心概念演示")
    print("=" * 50)
    
    # 创建示例词向量序列 (3个词，每个词4维向量)
    word_vectors = torch.tensor([
        [1.0, 2.0, 0.5, -1.0],  # 词1: "很"
        [0.8, -1.5, 2.0, 0.3],  # 词2: "好"
        [-0.5, 1.0, -0.8, 1.5]  # 词3: "看"
    ])
    
    print("输入词向量序列 (3个词 × 4维):")
    print(word_vectors.numpy())
    print()
    
    # 1. Mean Pooling
    mean_pooled = torch.mean(word_vectors, dim=0)
    print("1. Mean Pooling (平均池化):")
    print(f"   公式: (词1 + 词2 + 词3) / 3")
    print(f"   结果: {mean_pooled.numpy()}")
    print(f"   特点: 保留全局平均信息")
    print()
    
    # 2. Max Pooling
    max_pooled = torch.max(word_vectors, dim=0)[0]
    print("2. Max Pooling (最大池化):")
    print(f"   公式: max(词1, 词2, 词3) 按维度")
    print(f"   结果: {max_pooled.numpy()}")
    print(f"   特点: 突出显著特征")
    print()
    
    # 3. Sum Pooling
    sum_pooled = torch.sum(word_vectors, dim=0)
    print("3. Sum Pooling (求和池化):")
    print(f"   公式: 词1 + 词2 + 词3")
    print(f"   结果: {sum_pooled.numpy()}")
    print(f"   特点: 累积所有信息")
    print()
    
    # 4. Attention Pooling (简化版)
    # 假设注意力权重
    attention_weights = torch.softmax(torch.tensor([0.8, 1.2, 0.5]), dim=0)
    attention_pooled = torch.sum(attention_weights.unsqueeze(1) * word_vectors, dim=0)
    print("4. Attention Pooling (注意力池化):")
    print(f"   注意力权重: {attention_weights.numpy()}")
    print(f"   加权求和结果: {attention_pooled.numpy()}")
    print(f"   特点: 自动学习重要性权重")
    print()
    
    return {
        'mean': mean_pooled,
        'max': max_pooled,
        'sum': sum_pooled,
        'attention': attention_pooled
    }

def demonstrate_deep_learning_concepts():
    """演示深度学习核心概念"""
    print("=" * 50)
    print("深度学习核心概念演示")
    print("=" * 50)
    
    # 1. 线性变换
    print("1. 线性变换 (Linear Transformation):")
    input_dim = 4
    hidden_dim = 3
    
    # 创建权重矩阵和偏置
    W = torch.randn(input_dim, hidden_dim)
    b = torch.randn(hidden_dim)
    
    # 输入向量
    x = torch.tensor([1.0, 2.0, 0.5, -1.0])
    
    # 线性变换: y = xW + b
    linear_output = torch.matmul(x, W) + b
    
    print(f"   输入: {x.numpy()}")
    print(f"   权重矩阵形状: {W.shape}")
    print(f"   线性输出: {linear_output.numpy()}")
    print()
    
    # 2. 非线性激活
    print("2. 非线性激活函数:")
    relu_output = torch.relu(linear_output)
    sigmoid_output = torch.sigmoid(linear_output)
    tanh_output = torch.tanh(linear_output)
    
    print(f"   ReLU激活: {relu_output.numpy()}")
    print(f"   Sigmoid激活: {sigmoid_output.numpy()}")
    print(f"   Tanh激活: {tanh_output.numpy()}")
    print()
    
    # 3. 多层网络
    print("3. 多层神经网络:")
    layer1 = nn.Linear(4, 6)
    layer2 = nn.Linear(6, 3)
    layer3 = nn.Linear(3, 2)
    
    # 前向传播
    h1 = torch.relu(layer1(x))
    h2 = torch.relu(layer2(h1))
    output = layer3(h2)
    
    print(f"   输入层: {x.shape} -> 隐藏层1: {h1.shape}")
    print(f"   隐藏层1: {h1.shape} -> 隐藏层2: {h2.shape}")
    print(f"   隐藏层2: {h2.shape} -> 输出层: {output.shape}")
    print(f"   最终输出: {output.detach().numpy()}")
    print()

def visualize_pooling_comparison():
    """可视化不同pooling策略的效果"""
    # 创建更复杂的示例数据
    np.random.seed(42)
    sequence_length = 10
    vector_dim = 4
    
    # 模拟一个句子的词向量序列
    word_vectors = torch.randn(sequence_length, vector_dim)
    
    # 计算不同pooling结果
    pooling_results = {
        'Mean': torch.mean(word_vectors, dim=0),
        'Max': torch.max(word_vectors, dim=0)[0],
        'Sum': torch.sum(word_vectors, dim=0),
    }
    
    # 绘制对比图
    fig, axes = plt.subplots(2, 2, figsize=(12, 10))
    
    # 原始词向量序列
    axes[0, 0].imshow(word_vectors.T.numpy(), cmap='RdBu', aspect='auto')
    axes[0, 0].set_title('原始词向量序列\n(4维 × 10个词)')
    axes[0, 0].set_xlabel('词的位置')
    axes[0, 0].set_ylabel('向量维度')
    
    # 不同pooling结果对比
    pooling_names = list(pooling_results.keys())
    pooling_values = [pooling_results[name].numpy() for name in pooling_names]
    
    x_pos = np.arange(len(pooling_names))
    colors = ['skyblue', 'lightcoral', 'lightgreen']
    
    for i in range(vector_dim):
        axes[0, 1].bar(x_pos + i*0.2, [values[i] for values in pooling_values], 
                      width=0.2, label=f'维度{i+1}', alpha=0.7)
    
    axes[0, 1].set_title('不同Pooling策略结果对比')
    axes[0, 1].set_xlabel('Pooling策略')
    axes[0, 1].set_ylabel('数值')
    axes[0, 1].set_xticks(x_pos + 0.3)
    axes[0, 1].set_xticklabels(pooling_names)
    axes[0, 1].legend()
    axes[0, 1].grid(True, alpha=0.3)
    
    # 激活函数对比
    x = np.linspace(-3, 3, 100)
    axes[1, 0].plot(x, np.maximum(0, x), label='ReLU', linewidth=2)
    axes[1, 0].plot(x, 1/(1+np.exp(-x)), label='Sigmoid', linewidth=2)
    axes[1, 0].plot(x, np.tanh(x), label='Tanh', linewidth=2)
    axes[1, 0].set_title('常用激活函数')
    axes[1, 0].set_xlabel('输入值')
    axes[1, 0].set_ylabel('输出值')
    axes[1, 0].legend()
    axes[1, 0].grid(True, alpha=0.3)
    
    # 深度学习优势说明
    axes[1, 1].axis('off')
    advantages_text = """
深度学习的核心优势:

1. 自动特征学习
   • 传统方法: 手工设计特征
   • 深度学习: 自动从数据学习

2. 非线性建模能力
   • 通过激活函数引入非线性
   • 多层网络捕获复杂模式

3. 端到端训练
   • 统一优化所有组件
   • 避免误差传播累积

4. 强大的表示能力
   • 深层网络可以表示复杂函数
   • 适应各种类型的数据
    """
    
    axes[1, 1].text(0.05, 0.95, advantages_text, transform=axes[1, 1].transAxes,
                   fontsize=11, verticalalignment='top', fontfamily='SimHei')
    
    plt.tight_layout()
    plt.show()

def simple_classification_demo():
    """简单的分类演示"""
    print("=" * 50)
    print("简单分类演示")
    print("=" * 50)
    
    # 创建简单的二分类数据
    positive_features = torch.tensor([
        [1.5, 2.0, 0.8, 1.2],  # 正面情感特征
        [1.8, 1.5, 1.0, 1.5],
        [1.2, 2.2, 0.9, 1.1]
    ])
    
    negative_features = torch.tensor([
        [-1.2, -1.8, -0.5, -1.0],  # 负面情感特征
        [-1.5, -1.2, -0.8, -1.3],
        [-1.0, -2.0, -0.6, -0.9]
    ])
    
    # 创建简单的分类器
    classifier = nn.Sequential(
        nn.Linear(4, 8),
        nn.ReLU(),
        nn.Linear(8, 2)  # 2个类别
    )
    
    # 前向传播
    pos_logits = classifier(positive_features)
    neg_logits = classifier(negative_features)
    
    # 计算概率
    pos_probs = torch.softmax(pos_logits, dim=1)
    neg_probs = torch.softmax(neg_logits, dim=1)
    
    print("正面样本分类结果:")
    for i, (logit, prob) in enumerate(zip(pos_logits, pos_probs)):
        print(f"  样本{i+1}: 负面概率={prob[0]:.3f}, 正面概率={prob[1]:.3f}")
    
    print("\n负面样本分类结果:")
    for i, (logit, prob) in enumerate(zip(neg_logits, neg_probs)):
        print(f"  样本{i+1}: 负面概率={prob[0]:.3f}, 正面概率={prob[1]:.3f}")

def main():
    """主演示函数"""
    print("1-gram深度学习分类器 - 核心概念演示")
    print("本演示将帮助你理解:")
    print("• Pooling策略的工作原理")
    print("• 深度学习的基本概念")
    print("• 文本分类的基本流程")
    print()
    
    # 1. Pooling概念演示
    pooling_results = demonstrate_pooling_concepts()
    
    # 2. 深度学习概念演示
    demonstrate_deep_learning_concepts()
    
    # 3. 简单分类演示
    simple_classification_demo()
    
    # 4. 可视化对比
    print("=" * 50)
    print("生成可视化图表...")
    visualize_pooling_comparison()
    
    print("\n" + "=" * 50)
    print("核心概念总结:")
    print("=" * 50)
    print("1. 1-gram模型: 将文本看作独立词汇的集合")
    print("2. Pooling策略: 将变长序列转换为固定长度表示")
    print("   • Mean: 平均值，保留全局信息")
    print("   • Max: 最大值，突出显著特征")
    print("   • Sum: 求和，累积信息")
    print("   • Attention: 加权求和，自动学习重要性")
    print("3. 深度学习优势:")
    print("   • 自动特征学习")
    print("   • 非线性建模能力")
    print("   • 端到端训练")
    print("   • 强大的表示能力")

if __name__ == "__main__":
    main()